package edu.ruc.cluster.ui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
//import java.io.BufferedReader;
//import java.io.BufferedWriter;
//import java.io.FileNotFoundException;
//import java.io.FileReader;
//import java.io.FileWriter;
//import java.io.IOException;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.SoftBevelBorder;
import javax.swing.border.TitledBorder;
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.text.View;

import edu.ruc.cluster.util.ColumnLayout;
import edu.ruc.cluster.util.Const;
import edu.ruc.cluster.util.DefaultLogHandler;
import edu.ruc.cluster.util.HadoopFileFilter;
import edu.ruc.cluster.util.PropertyRetrieval;

/**
 * 2012-12-29
 * Much like JdkPane, used to:
 * 		--- get Hadoop installed file, or .tar.gz
 * 		--- get Hadoop install directory 
 * @author deke
 */
@SuppressWarnings("serial")
public class HadoopFilePane extends JPanel {
	private DefaultLogHandler logHandler = null;
	private PropertyRetrieval property = null;
	private JPanel dirPane = null;
	private JPanel installPane = null;
	
	private JPanel filePanel = null;
	private JLabel filePathLabel = null;
	private JTextField fileText = null;
	private JButton hadoopButton = null;
	private JFileChooser hadoopfc = null;
	private File hadoopfile = null;
	
	private JPanel inslower = null;
	private JPanel insInput = null;
//	private JLabel installLabel = null;
	private JTextField installText = null;
	
	private Border loweredBorder = null;
	private static Dimension HGAP10 = null;
	private static String FILE_LABEL = "Choose File";
//			"<html>Choose File:</html>";
	private static String DIR_LABEL = "Choose Directory:";
//			"<html>Choose Directory:</html>";
	
	private static String INPUT_DIR ;
//			"<html>please input directory:<html>";
	private static String DEFAULT_DIR ;
//			"<html>JDK will be installed this directory:</html>";
	
	private static int ncolumns = 15;
	
	private int label1height = 0;
	private int label2height = 0;
	private int maxLabelWidth = 150;
	
	public HadoopFilePane(){
	}
	public void consturctPane(){
//		logHandler = new DefaultLogHandler();
		logHandler = DefaultLogHandler.getInstance();
		property = new PropertyRetrieval(Const.CONFIG_FILE);
		INPUT_DIR = "Directory under /home/" + property.getString(Const.HADOOP_USER_TAG) + "/ :";
		DEFAULT_DIR = "hadoop will be installed in directory:";
		loweredBorder = new CompoundBorder(new SoftBevelBorder(SoftBevelBorder.LOWERED),
	            new EmptyBorder(5,5,5,5));
		HGAP10 = new Dimension(10, 1);
			 
		hadoopButton = new JButton("select");
		setupDirPanel();
		setupInstallPanel();	
		
		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		this.add(dirPane);
		this.add(installPane);
		this.setVisible(true);
	}
	
	/**
	 *  choose hadoop: can either be a directory or install file(.bin, .rpm or .tar.gz)
	 *  -------caption-------
	 *  ------end caption----
	 *  -------choose--------
	 *  ----p1---- ----filePanel----
	 *  - (yes)  - - select - 
	 *  - (no)   - - text   -
	 *  --end p1-- --end filePanel--
	 *  ----end choose-------
	 */
	private void setupDirPanel()
	{
		dirPane = new JPanel(new ColumnLayout());
		filePathLabel = new JLabel("");
		fileText = new JTextField(ncolumns);
		fileText.setEditable(false);
		hadoopButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				int state=hadoopfc.showOpenDialog(null);//open select dialog
				if(state==1){
					return;//cancel
				}
				else{
					hadoopfile = hadoopfc.getSelectedFile();//f is selected directory
					fileText.setText(hadoopfile.getAbsolutePath());
				}
				repaint();
			}
		});
		hadoopfc = new JFileChooser();
		hadoopfc.setCurrentDirectory(new File("~/"));
		
		JLabel caption = new JLabel("<html>Do you have an hadoop directory with proper configuration?</html>");
		caption.setFont(new Font("SansSerif.bold", Font.ITALIC, 16));
		caption.setForeground(Color.RED);
		
		JPanel choose = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 0));
//  		choose.setLayout(new BoxLayout(choose, BoxLayout.X_AXIS));
//		choose.setLayout(new GridLayout(1, 2, 20, 20));
  		
		JPanel p1 = createVerticalPanel(false);
		p1.setBorder(new CompoundBorder(
                new TitledBorder(
                  null, " ",
                  TitledBorder.LEFT, TitledBorder.TOP), new EmptyBorder(5, 5, 5, 5))
				);  		

		ButtonGroup g = new ButtonGroup();
		JRadioButton 
				rb1 = new JRadioButton("Yes", false),
				rb2 = new JRadioButton("No", false);
		
		ActionListener dirAction = new ActionListener(){
			public void actionPerformed(ActionEvent e){
				
				if(label1height == 0){
					String str = DIR_LABEL.length() > FILE_LABEL.length() ? DIR_LABEL : FILE_LABEL;
					JLabel tmp = new JLabel(str);
					View v = BasicHTML.createHTMLView(tmp, tmp.getText());		 
					v.setSize(maxLabelWidth, Integer.MAX_VALUE);
					label1height = (int) v.getMinimumSpan(View.Y_AXIS); 
				}	
				filePathLabel.setPreferredSize(new Dimension(maxLabelWidth, label1height));
				
				if(((JRadioButton)e.getSource()).getText().equals("Yes")){
					// choose directory
					filePathLabel.setText(DIR_LABEL);
					hadoopfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);//can only choose directory
					filePanel.setBorder(new TitledBorder(DIR_LABEL));
					filePanel.setVisible(true);
					logHandler.info("Only directory");
				}else{
					// choose .bin or .rpm or .tar.gz
					filePathLabel.setText(FILE_LABEL);
					hadoopfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
					hadoopfc.setFileFilter(new HadoopFileFilter());
					filePanel.setBorder(new TitledBorder(FILE_LABEL));
					filePanel.setVisible(true);
					logHandler.info("Only certain kind of file");
				}
			}
		};
		filePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
		
		rb1.addActionListener(dirAction);
		rb2.addActionListener(dirAction);
		g.add(rb1);
		g.add(rb2);
		
		p1.add(rb1);
		p1.add(Box.createRigidArea(HGAP10));
		p1.add(rb2);
		
//		filePanel.add(filePathLabel);
		filePanel.add(fileText);
		filePanel.add(hadoopButton);
		filePanel.setVisible(false);
		
		choose.add(p1);
		choose.add(filePanel);
		
		dirPane.add(caption);
		dirPane.add(choose);
	}
	
	private void setupInstallPanel(){
		
		installPane = new JPanel(new ColumnLayout());
		JLabel caption = new JLabel("<html>Do you want to specify the directory " +
				"for hadoop to install?</html>");
		caption.setFont(new Font("SansSerif.bold", Font.ITALIC, 16));
		caption.setForeground(Color.RED);
		
		inslower = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 0));
		JPanel p1 = createVerticalPanel(false);
		p1.setBorder(new CompoundBorder(
                new TitledBorder(
                  null, " ",
                  TitledBorder.LEFT, TitledBorder.TOP), new EmptyBorder(5, 5, 5, 5))
				);  		

		ButtonGroup g = new ButtonGroup();
		JRadioButton 
				rb1 = new JRadioButton("Yes", false),
				rb2 = new JRadioButton("No", false);
		ActionListener dirAction = new ActionListener(){
			public void actionPerformed(ActionEvent e){
				
				if(((JRadioButton)e.getSource()).getText().equals("Yes")){
					// choose directory
					hadoopfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);//can only choose directory
					setInstalledPanel(true);
				}else{
					// given the default directory
					setInstalledPanel(false);
				}
			}
		};
		insInput = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
		insInput.setVisible(false);
		rb1.addActionListener(dirAction);
		rb2.addActionListener(dirAction);
		g.add(rb1);
		g.add(rb2);
		p1.add(rb1);
		p1.add(Box.createRigidArea(HGAP10));
		p1.add(rb2);
		inslower.add(p1);
		inslower.add(insInput);
		installPane.add(caption);
		installPane.add(inslower);
	}
	private void setInstalledPanel(boolean Customerized){
		
		insInput.removeAll();
		
		if(Customerized == true){
			insInput.setBorder(new TitledBorder(INPUT_DIR));
//			if(installLabel == null)
//				installLabel = new JLabel(INPUT_DIR);
//			else 
//				installLabel.setText(INPUT_DIR);
			installText = new JTextField(ncolumns);
		}else{
			insInput.setBorder(new TitledBorder(DEFAULT_DIR));
//			if(installLabel == null)
//				installLabel = new JLabel(DEFAULT_DIR);
//			else
//				installLabel.setText(DEFAULT_DIR);
			installText = new JTextField(ncolumns);
			String str = "/home/" + property.getString(Const.HADOOP_USER_TAG) + "/hadoop/";
			installText.setText(str);
			installText.setEditable(false);
		}
		if(label2height == 0){
			String text = INPUT_DIR.length() > DEFAULT_DIR.length() ? INPUT_DIR : DEFAULT_DIR;
			JLabel tmp = new JLabel(text);
			View v = BasicHTML.createHTMLView(tmp, tmp.getText());		 
			v.setSize(maxLabelWidth, Integer.MAX_VALUE);
			label2height = (int) v.getMinimumSpan(View.Y_AXIS); 
		}	
//		installLabel.setPreferredSize(new Dimension(maxLabelWidth, label2height));

		insInput.add(installText);
			// Screw FlowLayout!!!!!!!!!!!!
		JLabel tmp = new JLabel("                 ");  // used for align select button
		insInput.add(tmp);
		
		insInput.setVisible(true);
		insInput.updateUI();
	}
	private JPanel createVerticalPanel(boolean threeD) {
        JPanel p = new JPanel();
        p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
        p.setAlignmentY(TOP_ALIGNMENT);
        p.setAlignmentX(LEFT_ALIGNMENT);
        if(threeD) {
            p.setBorder(loweredBorder);
        }
        return p;
    }
	
	@SuppressWarnings("unused")
	private JPanel createHorizontalPanel(boolean threeD) {
        JPanel p = new JPanel();
        p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
        p.setAlignmentY(TOP_ALIGNMENT);
        p.setAlignmentX(LEFT_ALIGNMENT);
        if(threeD) {
            p.setBorder(loweredBorder);
        }
        return p;
    }
	
	/**
	 * Used: append/update hadoop config information to Const.CONFIG_FILE
	 * 			Const.HADOOP_SRC_TAG: hadoop source(folder or .tar.gz) in this machine
	 * 			Const.HADOOP_DST_TAG: destination for hadoop folder (Relative path to /home/addUser)
	 * 2012-12-28 TODO:test store()
	 */
	public void store(){
		
			// should call PropertyRetrieval.putString() 
//		PropertyRetrieval pr = new PropertyRetrieval(Const.CONFIG_FILE, true);
		String str = installText.getText().toString().trim();
		str = str.replace("/home/" + property.getString(Const.HADOOP_USER_TAG) + "/", "");
		property.putString(Const.HADOOP_DST_TAG, str);
		property.putString(Const.HADOOP_SRC_TAG, hadoopfile.getAbsolutePath());
		/*
		try{
			boolean append = true;
			String srcContent = Const.HADOOP_SRC_TAG + Const.LINE_SEPERATOR + hadoopfile.getAbsolutePath() + "\n";
			String dstContent = Const.HADOOP_DST_TAG + Const.LINE_SEPERATOR + installText.getText().toString().trim() + "\n";
			BufferedReader reader = new BufferedReader(new FileReader(Const.CONFIG_FILE));
			String line = null;
			StringBuffer buffer = new StringBuffer();
			while((line = reader.readLine()) != null){
				String[] strs = line.split(Const.LINE_SEPERATOR);
				if(strs[0].equals(Const.HADOOP_DST_TAG)){
					buffer.append(dstContent);
					append = false;
				}else if(strs[0].equals(Const.HADOOP_SRC_TAG)){
					buffer.append(srcContent);
				}
				else
					buffer.append(line + "\n");
			}
			if(append == true){
				buffer.append(dstContent);
				buffer.append(srcContent);
			}
			reader.close();
			
			BufferedWriter writor = new BufferedWriter(new FileWriter(Const.CONFIG_FILE));
			writor.write(buffer.toString());
			writor.close();
			
		}catch(FileNotFoundException e){
			logHandler.error(this.getClass().getSimpleName() + " " + e.getMessage(), e);
		}catch(IOException e){
			logHandler.error(this.getClass().getSimpleName() + " " + e.getMessage(), e);
		}
		*/
		/*
		try{
			BufferedWriter writor = new BufferedWriter(new FileWriter(new File(Const.HADOOP_CONF_FILE)));
			writor.write(Const.HADOOP_DST_TAG + Const.LINE_SEPERATOR + installText.getText().toString().trim() + "\n");
			writor.write(Const.HADOOP_SRC_TAG + Const.LINE_SEPERATOR + hadoopfile.getAbsolutePath() + "\n");
			writor.close();
		}catch(IOException e){
			logHandler.error(this.getClass().getSimpleName() + e.getMessage(), e);
		}
		*/
	}
	public boolean ok(){
		// TODO: check hadoopfile format, like containing conf/core-site.xml, slaves, etc
		if(installText.getText().trim().isEmpty() || hadoopfile == null)
			return false;
		String dir = installText.getText().trim();
		logHandler.info("installed dir : " + dir);
		logHandler.info("dir.isEmpty(): " + dir.isEmpty() + "\tdir.matches():" + dir.matches("(\\S+/)*\\S+/?"));
		logHandler.info("hadoopfile: " + hadoopfile.getAbsolutePath().matches("(/\\S+)*/?"));
		logHandler.info(hadoopfile.getAbsolutePath());
		if(dir.matches("(\\S+/)*\\S+/?") && hadoopfile.getAbsolutePath().matches("(/\\S+)*/?"))
			return true;
		else 
			return false;
	}
}
